﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;



namespace BadHabit.Factory.Controls {
    /// <summary>
    /// Interaction logic for SprintItemsPanel.xaml
    /// </summary>
    public partial class BacklogItemListBox : ListBox {


        /// <summary>
        ///  This struct helps to identify uniquely a backlogitem resume row.
        /// </summary>
        public struct VisibleBacklogItemIdentity {
            public string BacklogItemUId { get; set; }
            public string SprintUId { get; set; }          
        }    

        // this is a key for the BacklogItem property
        internal static readonly DependencyPropertyKey SelectedBacklogItemKey =
            DependencyProperty.RegisterReadOnly("SelectedBacklogItem",
            typeof(System.Data.DataRowView),
            typeof(BacklogItemListBox),
            new PropertyMetadata(null)
        );


        /// <summary>
        /// DP property for the SelectedBacklogItem.
        /// </summary>
        public static readonly DependencyProperty SelectedBacklogItemProperty = SelectedBacklogItemKey.DependencyProperty;

        /// <summary>
        /// Gets the selected project.
        /// </summary>
        public System.Data.DataRowView SelectedBacklogItem {
            get { return (System.Data.DataRowView)GetValue(SelectedBacklogItemProperty); }
            set {
                if (value == null) {
                    SelectedItem = null;
                    return;
                }                
                System.Data.DataView collectionView = ItemsSource as System.Data.DataView;
                if (collectionView == null)
                    return;

                if (string.IsNullOrEmpty(collectionView.Sort))
                    collectionView.Sort = "SprintNumber, BusinessValue, BacklogItemNumber, BaseLine";

                int idx = collectionView.Find(new object[] { value["SprintNumber"], value["BusinessValue"], value["BacklogItemNumber"], value["BaseLine"] });

                if (idx >= 0)
                    SelectedItem = collectionView[idx];

            }
        }



        
        /// <summary>
        /// Default contructor.
        /// </summary>
        public BacklogItemListBox() {
            InitializeComponent();            
           
        }
                      
        /// <summary>
        /// Returns the sprint number filter.
        /// </summary>
        /// <param name="value">The sprint number</param>
        /// <returns>A string with the filter</returns>
        private string GetsSprintNumberFilter(short value) {            
            string  sprintNumberFilter = "(SprintNumber >= 0)";
            if(Project==null)
                return sprintNumberFilter;

            // Dailly tasks
            if (value == 0) {
                if (Project.CurrentSprint == null) {
                    if(Project.LastSprint!=null)
                        sprintNumberFilter = "(SprintNumber=" + Project.LastSprint.SprintNumber + ")";
                    else
                        sprintNumberFilter = "(SprintNumber >=0)";
                } else {
                    if (!Project.CurrentSprint.IsExpirationDateNull())
                        sprintNumberFilter = "(SprintNumber=" + Project.CurrentSprint.SprintNumber + ")";
                }
            }
            // sprint was selected
            else if (value > 0 && value <= Project.LastSprint.SprintNumber)
                sprintNumberFilter = "(SprintNumber=" + value + ")";

            return sprintNumberFilter;
        }

        /// <summary>
        /// Returns backlog item number filter.
        /// <param name="value">List of backlog items numbers</param>
        /// <returns>A string with the filter</returns>
        /// </summary>
        private string GetsBacklogItemFilter(VisibleBacklogItemIdentity[] value) {
            if(value==null)
                return "(1=0)";
            if (value.Length == 0)
                return "(1=0)";
            StringBuilder sb = new StringBuilder("(");
            for (int i = 0; i < value.Length; i++) {
                sb.Append("(BacklogItemUId='" + value[i].BacklogItemUId + "' AND SprintUId='" + value[i].SprintUId + "')");
                if (i != value.Length - 1)
                    sb.Append(" OR ");
            }
            sb.Append(")");
            return sb.ToString();            
        }

        public short SprintNumberFilter { get; set; }
        public VisibleBacklogItemIdentity[] BacklogItemFilter { get; set; }



        private void UserControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) {
            //RefreshFilter();
            

        }

        public void RefreshFilter() {
            Data.ProjectDataSet dsProject = DataContext as Data.ProjectDataSet;
            if (dsProject == null)
                return;

            
            ItemsSource = dsProject.VisibleBacklogItem.DefaultView;
                        

            ApplyFilter();
        }

        /// <summary>
        /// Sets the sprint number and backlog item number filter that defines with backlog items are displayed.
        /// Sprint Zero means dailly tasks filter.  
        /// Sprint above the SprintCount, means all backlog items.
        /// </summary>
        public void ApplyFilter() {

            
            BindingListCollectionView collectionView = (BindingListCollectionView)CollectionViewSource.GetDefaultView(ItemsSource);


            if (collectionView == null)
                return;

            string sprintStr = GetsSprintNumberFilter(SprintNumberFilter);
            string backlogItemStr = GetsBacklogItemFilter(BacklogItemFilter);

            // NEED THIS before use "collectionView.CustomFilter" otherwise we got an exception
            if (collectionView.IsAddingNew)
                collectionView.CommitNew();

            if (collectionView.IsEditingItem)
                collectionView.CommitEdit();

            if (SprintNumberFilter == 0)
                collectionView.CustomFilter = "(IsVisible=1 and " + sprintStr + ") or (IsVisible=1 and " + backlogItemStr + ")";
            else
                collectionView.CustomFilter = "IsVisible=1 and " + sprintStr;

            collectionView.GroupDescriptions.Clear();
            collectionView.GroupDescriptions.Add(new PropertyGroupDescription("SprintNumber"));

            collectionView.SortDescriptions.Clear();
            collectionView.SortDescriptions.Add(new System.ComponentModel.SortDescription("SprintNumber", System.ComponentModel.ListSortDirection.Ascending));
            collectionView.SortDescriptions.Add(new System.ComponentModel.SortDescription("BusinessValue", System.ComponentModel.ListSortDirection.Descending));
            collectionView.SortDescriptions.Add(new System.ComponentModel.SortDescription("BacklogItemNumber", System.ComponentModel.ListSortDirection.Ascending));
            collectionView.SortDescriptions.Add(new System.ComponentModel.SortDescription("BaseLine", System.ComponentModel.ListSortDirection.Ascending));

            
              

        }
        


        /// <summary>
        /// Gets the selected project.
        /// </summary>
        private Data.ProjectDataSet.ProjectRow Project {
            get {
                Data.ProjectDataSet dsProject = DataContext as Data.ProjectDataSet;
                if (dsProject == null)
                    return null;

                if (dsProject.Project.Count == 0)
                    return null;

                return dsProject.Project[0];
            }
        }

        // use this flag to unselect a item when clicked
        bool unselectedingItems = false;

        /// <summary>
        /// Every time the selected backlog item changes, set the dependency property.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
            
            // Do all this stuff in order to unselect an item when its clicked
            if (unselectedingItems)
                return;
            unselectedingItems = true;

            SelectedItems.Clear();
            if (e.AddedItems.Count > 0)
                SelectedItem = e.AddedItems[0];
            else
                SelectedItem = null;
            SetValue(SelectedBacklogItemKey, SelectedItem);
            unselectedingItems = false;
            
        }

        private void BacklogItem_Drop(object sender, DragEventArgs e) {

            if (!e.Data.GetDataPresent(typeof(Data.TaskDataSet.TaskRow)))
                return;

            FrameworkElement element = sender as FrameworkElement;
            if (element == null)
                return;

            System.Data.DataRow item = Helper.GetRowFromRowView<System.Data.DataRow>(element.DataContext);

            Data.TaskDataSet.TaskRow taskRow = (Data.TaskDataSet.TaskRow)e.Data.GetData(typeof(Data.TaskDataSet.TaskRow));

            TaskPanelBase.MoveTask(taskRow, item["SprintUId"].ToString(), item["BacklogItemUId"].ToString(), (short)item["BacklogItemNumber"], true);

            

            

        }

        private void BacklogItem_DragOver(object sender, DragEventArgs e) {
            if (!e.Data.GetDataPresent(typeof(Data.TaskDataSet.TaskRow)))
                e.Effects = DragDropEffects.None;
            else
                e.Effects = DragDropEffects.Move;
        }

        

        //private void listBoxItem_DoubleClick(object sender, MouseButtonEventArgs e) {
        //    ListBoxItem listItem = sender as ListBoxItem;
        //    if (sender == null)
        //        return;
        //    SelectedItem = listItem.DataContext;
        //    e.Handled = true;
        //    OpenBacklogItemDetailWindow();
        //}

        private void detailsMenuItem_Click(object sender, RoutedEventArgs e) {
            MenuItem item = sender as MenuItem;
            SelectedItem = item.DataContext;
            OpenBacklogItemDetailWindow();            
            
        }

        private void OpenBacklogItemDetailWindow() {
            if (SelectedItem == null)
                return;
            BindingListCollectionView collectionView =
            (BindingListCollectionView)CollectionViewSource.GetDefaultView(ItemsSource);
            Views.BacklogItemDetail w = new BadHabit.Factory.Views.BacklogItemDetail(Project, collectionView);
            w.Show();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e) {
            RefreshFilter();
        }
      



        

        

    }
}
